package com.dkm.nettysocketdemo.untils.jwt.intertfaceceptor;


import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.dkm.nettysocketdemo.constanct.CodeType;
import com.dkm.nettysocketdemo.exception.ApplicationException;
import com.dkm.nettysocketdemo.myWebsite.domain.HelmetClient;
import com.dkm.nettysocketdemo.untils.Tools;
import com.dkm.nettysocketdemo.untils.jwt.JWTVerifier;
import com.dkm.nettysocketdemo.untils.jwt.intertfaceceptor.domain.Code;
import com.dkm.nettysocketdemo.untils.jwt.intertfaceceptor.domain.CustomException;
import com.dkm.nettysocketdemo.untils.jwt.intertfaceceptor.domain.LocalUser;
import com.dkm.nettysocketdemo.untils.jwt.jwtutils.TokenUtil;
import com.dkm.nettysocketdemo.untils.jwt.login.PassToken;
import com.dkm.nettysocketdemo.untils.jwt.login.UserLoginToken;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * @PROJECT_NAME: orproject
 * @DESCRIPTION:  拦截器去获取token并验证token
 * @USER: 周佳佳
 * @DATE: 2020/7/23 11:16
 */
public class AuthenticationInterceptor implements HandlerInterceptor {

    @Autowired
    private LocalUser localUser;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token=request.getHeader("token");
        // 如果不是映射到方法直接通过
        if(!(handler instanceof HandlerMethod)){
            return true;
        }
        HandlerMethod handlerMethod= (HandlerMethod) handler;
        Method method=handlerMethod.getMethod();
        //检查是否有passtoken注释，有则跳过认证
        if (method.isAnnotationPresent(PassToken.class)) {
            PassToken passToken = method.getAnnotation(PassToken.class);
            if (passToken.required()) {
                return true;
            }
        }
        //检查有没有需要用户权限的注解
        if (method.isAnnotationPresent(UserLoginToken.class)) {
            UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);
            if (userLoginToken.required()) {
                if (Tools.isEmpty(token)) {
                    throw new CustomException(Code.TOKEN_OVERDUE_ERROR,"无token，请重新登录");
                }
                // 获取 token 中的 user 信息
                HelmetClient client = getUserInfo(token);
                //为false直接抛异常
                if(!JWTVerifier.isVerify(token,client)){
                    throw new CustomException(Code.TOKEN_OVERDUE_ERROR,"无token，身份不匹配");
                }
                //获得解密后claims对象
                Claims jwt = TokenUtil.parseJWTone(token,client);
                JSONObject jsonObject;
                jsonObject = (JSONObject) JSONObject.toJSON(jwt);

                //取出失效时间
                String exp = jsonObject.getString("exp");
                Long date=Long.valueOf(exp);
                long time = System.currentTimeMillis();
                String t = String.valueOf(time/1000);
                Long date2=Long.valueOf(t);
                //判断token时间是否过期 erpDate大于date当前时间返回false
                if (date2>date) {
                    throw new CustomException(Code.TOKEN_OVERDUE_ERROR,"token过期");
                }
                return true;
            }
        }
        return true;
    }

    /**
     * 从token中获取个人信息
     * @param token token
     * @return
     */
    private HelmetClient getUserInfo (String token) {
        // 获取 token 中的 user信息
        HelmetClient client = new HelmetClient();
        // MyUser query = new MyUser();
        try {
            client.setPkClientId(JWT.decode(token).getClaim("id").asString());
            client.setClientPhoneNumber(JWT.decode(token).getClaim("phoneNumber").asString());
            client.setClientName(JWT.decode(token).getClaim("name").asString());
            client.setClientHeadPortrait(JWT.decode(token).getClaim("headPortrait").asString());
            client.setClientMail(JWT.decode(token).getClaim("mail").asString());
            client.setClientAccountNumber(JWT.decode(token).getClaim("accountNumber").asString());
        } catch (JWTDecodeException j) {
            throw new ApplicationException(CodeType.OVENDU_ERROR,"token错误");
        }
        localUser.setUser(client);
        return client;
    }


    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}
